package com.scau402.system1.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.scau402.common.utils.PageUtils;
import com.scau402.system1.domain.bo.WmsJadeBO;
import com.scau402.system1.domain.bo.WmsJadeFeatureBO;
import com.scau402.system1.domain.bo.WmsJadeImageBO;
import com.scau402.system1.domain.bo.WmsJadeTypeBO;
import com.scau402.system1.domain.dto.CalWarehouseNumAndValueDTO;
import com.scau402.system1.domain.dto.WarehouseStorage;
import com.scau402.system1.domain.factory.WmsJadeFactory;
import com.scau402.system1.domain.po.*;
import com.scau402.system1.domain.query.InboundJadeQuery;
import com.scau402.system1.mapper.WmsJadeFeatureMapperV2;
import com.scau402.system1.mapper.WmsJadeImageMapperV2;
import com.scau402.system1.mapper.WmsJadeMapperV2;
import com.scau402.system1.mapper.WmsJadeTypeMapperV2;
import com.scau402.system1.repository.IWmsJadeRepository;
import io.jsonwebtoken.lang.Collections;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 
 * @create 2024/1/3 15:56
 * @description
 */
@Repository
@Slf4j
public class WmsJadeRepositoryImpl implements IWmsJadeRepository {
    @Getter
    private Map<Long, WmsJadeTypeBO> jadeTypeBOMap = new HashMap<>();

    @Autowired
    private WmsJadeMapperV2 wmsJadeMapper;

    @Autowired
    private WmsJadeFeatureMapperV2 wmsJadeFeatureMapper;

    @Autowired
    private WmsJadeImageMapperV2 wmsJadeImageMapper;

    @Autowired
    private WmsJadeTypeMapperV2 wmsJadeTypeMapper;

    @Autowired
    private WmsJadeFactory wmsJadeFactory;

    @PostConstruct
    public void initJadeTypeBOMap() {
        jadeTypeBOMap = wmsJadeFactory.toJadeTypeBOMap(wmsJadeTypeMapper.selectList
                (Wrappers.<WmsJadeTypePO>lambdaQuery().eq(WmsJadeTypePO::getDelFlag, '0'))
        );
    }

    // TODO  2024/1/5 3:35: 后续引入Spring Cache提高性能
    @Override
    public Map<String, List<WmsJadeBO>> findByInboundOrderCodeList(List<String> inboundOrderCodeList, Long tenantId) {
        log.info("inboundOrderCodeList：{}", inboundOrderCodeList);
        log.info("tenantId：{}", tenantId);

        // 查询入库单PO列表
        List<WmsJadePO> wmsJadePOList = CollectionUtils.isEmpty(inboundOrderCodeList) ? new ArrayList<>(0) :
                wmsJadeMapper.selectList(Wrappers.<WmsJadePO>lambdaQuery()
                        .eq(WmsJadePO::getTenantId, tenantId)
                        .eq(WmsJadePO::getDelFlag, '0')
                        .in(WmsJadePO::getOrderCode, inboundOrderCodeList));
        if (Collections.isEmpty(wmsJadePOList)) {
            log.warn("入库单列表为空，入库单编号：{}", inboundOrderCodeList);
            return new HashMap<>(0);
        }

        // 转化为jadeId列表
        List<Long> jadeIdList = wmsJadePOList.stream().map(WmsJadePO::getId).collect(Collectors.toList());

        // 查询翡翠特征PO列表
        List<WmsJadeFeaturePO> jadeFeaturePOList = getJadeFeaturePOList(jadeIdList, tenantId);

        // 查询翡翠图片map,key=图片id，value=图片
        List<Long> imageIdList = jadeFeaturePOList.stream().map(WmsJadeFeaturePO::getImageId).collect(Collectors.toList());
        Map<Long, WmsJadeImageBO> jadeImageBOMap = getJadeImagePOList(imageIdList, tenantId)
                .stream()
                .map(wmsJadeFactory::toWmsJadeImageBO)
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(WmsJadeImageBO::getId, Function.identity()));

        // 转化为翡翠特征BO列表
        List<WmsJadeFeatureBO> jadeFeatureBOList = Optional
                .ofNullable(wmsJadeFactory.toWmsJadeFeatureBOList(jadeFeaturePOList, jadeImageBOMap))
                .orElse(new ArrayList<>(0));

        // key=入库单编号，value=翡翠BO列表
        Map<String, List<WmsJadeBO>> jadeBOMap = wmsJadePOList.stream()
                .map(x -> wmsJadeFactory.toWmsJadeBO(x, jadeTypeBOMap.get(x.getJadeTypeId()), jadeFeatureBOList))
                .collect(Collectors.groupingBy(WmsJadeBO::getOrderCode));
        // 收集value为空的key列表
        List<String> emptyKeyList = new ArrayList<>();
        if (Collections.isEmpty(jadeBOMap)) {
            emptyKeyList.addAll(inboundOrderCodeList);
        } else {
            jadeBOMap.forEach((key, value) -> {
                if (Collections.isEmpty(value)) {
                    emptyKeyList.add(key);
                }
            });
        }
        if (emptyKeyList.size() > 0) {
            log.error("以下入库单的翡翠为空，入库单编号：{}", emptyKeyList);
        }

        return jadeBOMap;
    }

    // TODO  2024/1/5 3:35: 后续引入Spring Cache提高性能
    @Override
    public List<WmsJadeBO> getByCondition(InboundJadeQuery query, boolean page) {
        log.info("inboundJadeQuery：{}", query);
        log.info("tenantId：{}", query.getTenantId());

        // 查询入库单PO列表
        WmsJadePO wmsJadePO = wmsJadeFactory.toWmsJadePO(query);
        if (Objects.isNull(wmsJadePO)) {
            log.warn("入库货品查询条件为空，查询条件：{}", query);
            return new ArrayList<>(0);
        }
        // 默认查询未删除的
        wmsJadePO.setDelFlag("0");
        LambdaQueryWrapper<WmsJadePO> queryWrapper = Wrappers.lambdaQuery(wmsJadePO).orderByDesc(WmsJadePO::getCreateTime);
        // 分页
        if (page) {
            PageUtils.startPage();
        }
        List<WmsJadePO> wmsJadePOList = wmsJadeMapper.selectList(queryWrapper);
        // wmsJadePOList是Page类型携带分页信息的，需要将分页信息设置到MDC中
        if (page) {
            PageInfo<WmsJadePO> pageInfo = new PageInfo<>(wmsJadePOList);
            PageUtils.fetchSessionPageInfo(pageInfo);
        }
        log.info("wmsJadePOList size：{}", wmsJadePOList.size());
        log.info("wmsJadePOList：{}", wmsJadePOList);
        if (Collections.isEmpty(wmsJadePOList)) {
            log.warn("入库货品列表为空，查询条件：{}", query);
            return new ArrayList<>(0);
        }

        // 转化为jadeId列表
        List<Long> jadeIdList = wmsJadePOList.stream().map(WmsJadePO::getId).collect(Collectors.toList());

        // 查询翡翠特征PO列表
        List<WmsJadeFeaturePO> jadeFeaturePOList = getJadeFeaturePOList(jadeIdList, query.getTenantId());

        // 查询翡翠图片map,key=图片id，value=图片
        List<Long> imageIdList = jadeFeaturePOList.stream().map(WmsJadeFeaturePO::getImageId).collect(Collectors.toList());
        Map<Long, WmsJadeImageBO> jadeImageBOMap = getJadeImagePOList(imageIdList, query.getTenantId())
                .stream()
                .map(wmsJadeFactory::toWmsJadeImageBO)
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(WmsJadeImageBO::getId, Function.identity()));

        // 转化为翡翠特征BO列表
        List<WmsJadeFeatureBO> jadeFeatureBOList = Optional
                .ofNullable(wmsJadeFactory.toWmsJadeFeatureBOList(jadeFeaturePOList, jadeImageBOMap))
                .orElse(new ArrayList<>(0));

        List<WmsJadeBO> jadeBOList = wmsJadePOList.stream()
                .map(x -> wmsJadeFactory.toWmsJadeBO(x, jadeTypeBOMap.get(x.getJadeTypeId()), jadeFeatureBOList))
                .collect(Collectors.toList());
        log.info("jadeBOList size：{}", jadeBOList.size());

        return jadeBOList;
    }

    @Override
    public List<WmsJadeBO> findByIds(List<Long> jadeIdList, Long tenantId) {
        if (Collections.isEmpty(jadeIdList)) {
            log.warn("翡翠id列表为空，翡翠id列表：{}", jadeIdList);
            return new ArrayList<>(0);
        }
        List<WmsJadePO> wmsJadePOList = getWmsJadePOList(jadeIdList, tenantId);

        // 查询翡翠特征PO列表
        List<WmsJadeFeaturePO> jadeFeaturePOList = getJadeFeaturePOList(jadeIdList, tenantId);

        // 查询翡翠图片map,key=图片id，value=图片
        List<Long> imageIdList = jadeFeaturePOList.stream().map(WmsJadeFeaturePO::getImageId).collect(Collectors.toList());
        Map<Long, WmsJadeImageBO> jadeImageBOMap = getJadeImagePOList(imageIdList, tenantId)
                .stream()
                .map(wmsJadeFactory::toWmsJadeImageBO)
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(WmsJadeImageBO::getId, Function.identity()));

        // 转化为翡翠特征BO列表
        List<WmsJadeFeatureBO> jadeFeatureBOList = Optional
                .ofNullable(wmsJadeFactory.toWmsJadeFeatureBOList(jadeFeaturePOList, jadeImageBOMap))
                .orElse(new ArrayList<>(0));

        List<WmsJadeBO> jadeBOList = wmsJadePOList.stream()
                .map(x -> wmsJadeFactory.toWmsJadeBO(x, jadeTypeBOMap.get(x.getJadeTypeId()), jadeFeatureBOList))
                .collect(Collectors.toList());
        log.info("jadeBOList size：{}", jadeBOList.size());

        return jadeBOList;
    }

    /**
     * 计算指定仓库/仓位中所有在仓翡翠的数量和价值
     * @param warehouseId 仓库DO
     * @param storageId 仓位DO
     * @return
     */
    @Override
    public CalWarehouseNumAndValueDTO countNumAndPrice(Long warehouseId, Long storageId) {
        //未指定仓位
        if(storageId==null){
            //计算仓库总价值和总量
            return wmsJadeMapper.selectTotalPriceByWarehouseId(warehouseId);
        }
        //指定了对应仓位
        else {
            //计算仓位总价值和总量
            return wmsJadeMapper.selectTotalPriceByStorageId(storageId);
        }
    }

    /**
     * 计算总量和总值
     * @param targetList 仓库仓位列表
     * @return 统计结果
     */
    @Override
    public CalWarehouseNumAndValueDTO countNumAndPrice2(List<WarehouseStorage> targetList) {
        return wmsJadeMapper.selectTotalPriceByWareStorageId(targetList);
    }

    @Override
    public List<WmsCheckboundJadeDetailPO> selectJadeDetailListByWarehouseStorage(List<WarehouseStorage> targetList) {
        return wmsJadeMapper.selectJadeDetailListByWarehouseStorage(targetList);
    }

    /**
     * 根据仓库id获取相关的在仓的翡翠详情信息
     * @param warehouseId 仓库id
     * @return
     */
    @Override
    public List<WmsCheckboundJadeDetailPO> selectJadeDetailListByWarehouseId(Long warehouseId) {
        return wmsJadeMapper.selectJadeDetailByWarehouseId(warehouseId);
    }

    @Override
    public List<WmsCheckboundJadeDetailPO> selectRelatedJadeDetail(Long warehouseId, List<Long> relatedStorageIds) {
        return wmsJadeMapper.selectJadeDetailByRelatedStorageIds(warehouseId, relatedStorageIds);
//        return wmsJadeMapper.selectList(new QueryWrapper<WmsJadePO>()
//                .select("jade_name","jade_barcode","storage_id","warehouse_id",
//                        "sum(jade_quantity) as jade_quantity",
//                        "sum(outbound_quantity) as outbound_quantity",
//                        "jade_cost","jade_tag_price","jade_market_price")
//                .in("storage_id",relatedStorageIds)
//                .groupBy("jade_barcode","jade_name","warehouse_id","jade_cost","jade_tag_price","jade_market_price"));
    }

    @Override
    public Long selectOneImageIdByBarcode(String jadeBarcode) {
        return wmsJadeMapper.selectImageIdByBarcode(jadeBarcode).getImageId();
    }

    /**
     * 根据翡翠id获取翡翠信息列表
     * @param jadeIdList 翡翠id列表
     * @return 对应的翡翠PO列表
     */
    @Override
    public List<WmsJadePO> findJadeByIds(List<Long> jadeIdList) {
        return Optional.ofNullable(wmsJadeMapper.selectList(new QueryWrapper<WmsJadePO>().in("id",jadeIdList))).orElse(new ArrayList<>());
    }

    /**
     * 通过翡翠id设置翡翠可见性（del_flag），
     * 仅能设置可见性（del_flag = "0" 和 del_flag = "1"），删除请另寻方法
     * @param jadeId 翡翠id
     * @param jadeVisible 可见性：仅支持"0"：可见、"1"：不可见
     */
    @Override
    public void updateVisibleByJadeId(Long jadeId, String jadeVisible) {
        if(!jadeVisible.equals("0") && !jadeVisible.equals("1")) return;
        log.info(jadeVisible);
        wmsJadeMapper.updateVisibleByJadeId(jadeId,jadeVisible);
    }

    /**
     * 通过翡翠id设置翡翠状态
     * @param jadeId 翡翠id
     * @param jadeStatus 翡翠状态 1：在仓、2：借出、3：售出、4：还出、5：加工出库
     * @see com.scau402.common.constant.JadeConstants
     */
    @Override
    public void updateStatusByJadeId(Long jadeId, String jadeStatus) {
        if(!jadeStatus.equals("1")&&!jadeStatus.equals("2")&&!jadeStatus.equals("3")&&!jadeStatus.equals("4")&&!jadeStatus.equals("5")) return;
        wmsJadeMapper.updateStatusByJadeId(jadeId,jadeStatus);
    }

    @Override
    public WmsJadePO findQuantityByJadeId(Long jadeId) {
        return wmsJadeMapper.findQuantityByJadeId(jadeId);
    }

    //private List<WmsJadePO> getWmsJadePOListByCondition(Wrapper<WmsJadePO> queryWrapper) {
    //    return Optional
    //            .ofNullable(wmsJadeMapper.selectList(queryWrapper))
    //            .orElse(new ArrayList<>(0));
    //}

    private List<WmsJadePO> getWmsJadePOList(List<Long> jadeIdList, Long tenantId) {
        return CollectionUtils.isEmpty(jadeIdList) ? new ArrayList<>(0) : Optional
                .ofNullable(wmsJadeMapper.selectList(Wrappers.<WmsJadePO>lambdaQuery()
                        .eq(WmsJadePO::getTenantId, tenantId)
                        .eq(WmsJadePO::getDelFlag, '0')
                        .in(WmsJadePO::getId, jadeIdList))
                )
                .orElse(new ArrayList<>(0));
    }

    /**
     * 根据翡翠id列表查询翡翠特征PO列表
     *
     * @param jadeIdList
     * @param tenantId
     * @return
     */
    private List<WmsJadeFeaturePO> getJadeFeaturePOList(List<Long> jadeIdList, Long tenantId) {
        return CollectionUtils.isEmpty(jadeIdList) ? new ArrayList<>(0) : Optional
                .ofNullable(wmsJadeFeatureMapper.selectList(Wrappers.<WmsJadeFeaturePO>lambdaQuery()
                        .eq(WmsJadeFeaturePO::getTenantId, tenantId)
                        .eq(WmsJadeFeaturePO::getDelFlag, '0')
                        .in(WmsJadeFeaturePO::getJadeId, jadeIdList))
                )
                .orElse(new ArrayList<>(0));
    }

    /**
     * 根据图片id列表查询翡翠图片PO列表
     *
     * @param imageIdList
     * @param tenantId
     * @return
     */
    private List<WmsJadeImagePO> getJadeImagePOList(List<Long> imageIdList, Long tenantId) {
        return CollectionUtils.isEmpty(imageIdList) ? new ArrayList<>(0) : Optional
                .ofNullable(wmsJadeImageMapper.selectList(Wrappers.<WmsJadeImagePO>lambdaQuery()
                        .eq(WmsJadeImagePO::getTenantId, tenantId)
                        .eq(WmsJadeImagePO::getDelFlag, '0')
                        .in(WmsJadeImagePO::getId, imageIdList))
                )
                .orElse(new ArrayList<>(0));
    }

}
